package com.easylinkin.linkappapi.powerdistribution.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.additional.query.impl.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.additional.update.impl.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.linkappapi.common.exceptions.BusinessException;
import com.easylinkin.linkappapi.common.service.CommonService;
import com.easylinkin.linkappapi.powerdistribution.entity.DistributionCabinet;
import com.easylinkin.linkappapi.powerdistribution.entity.DistributionCabinetAlarmConfig;
import com.easylinkin.linkappapi.powerdistribution.entity.DistributionCabinetRefDevice;
import com.easylinkin.linkappapi.powerdistribution.mapper.DistributionCabinetAlarmConfigMapper;
import com.easylinkin.linkappapi.powerdistribution.mapper.DistributionCabinetMapper;
import com.easylinkin.linkappapi.powerdistribution.service.DistributionCabinetRefDeviceService;
import com.easylinkin.linkappapi.powerdistribution.service.DistributionCabinetService;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import com.easylinkin.linkappapi.security.entity.LinkappUser;
import java.util.List;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

/**
 * <p>
 * 配电柜 服务实现类
 * </p>
 *
 * @author TongJie
 * @since 2020-08-05
 */
@Service
public class DistributionCabinetServiceImpl extends ServiceImpl<DistributionCabinetMapper, DistributionCabinet> implements DistributionCabinetService {

    private static final Logger LOGGER = LoggerFactory.getLogger(DistributionCabinetServiceImpl.class);

    @Resource
    private CommonService commonService;
    @Resource
    private LinkappUserContextProducer linkappUserContextProducer;
    @Resource
    private DistributionCabinetRefDeviceService distributionCabinetRefDeviceService;
    @Resource
    private DistributionCabinetAlarmConfigMapper distributionCabinetAlarmConfigMapper;

    @Override
    public void add(DistributionCabinet distributionCabinet) {
        validParamRequired(distributionCabinet);
        validParamFormat(distributionCabinet);
        validRepeat(distributionCabinet);
        commonService.setCreateAndModifyInfo(distributionCabinet);
        LinkappUser user = linkappUserContextProducer.getCurrent();
        distributionCabinet.setTenantId(user.getTenantId());
        saveOrUpdate(distributionCabinet);

        List<DistributionCabinetRefDevice> distributionCabinetRefDeviceList = distributionCabinet.getDistributionCabinetRefDeviceList();

        List<String> deviceCodes = distributionCabinetRefDeviceList.stream().map(DistributionCabinetRefDevice::getDeviceCode).collect(Collectors.toList());

        deviceCodes.forEach(deviceCode -> Assert.isTrue(deviceCodes.indexOf(deviceCode) == deviceCodes.lastIndexOf(deviceCode), "同一设备被关联2次或以上，请检查参数"));

        Assert.notEmpty(distributionCabinetRefDeviceList, "distributionCabinetRefDeviceList 不能为空");
        distributionCabinetRefDeviceList.forEach(distributionCabinetRefDevice -> {
            distributionCabinetRefDevice.setDistributionCabinetId(distributionCabinet.getId());
            distributionCabinetRefDeviceService.add(distributionCabinetRefDevice);
        });
    }


    /**
     * 校验重复
     */
    private void validRepeat(DistributionCabinet distributionCabinet) {
        QueryWrapper<DistributionCabinet> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name", distributionCabinet.getName());
        queryWrapper.eq("distribution_room_id", distributionCabinet.getDistributionRoomId());
        List<DistributionCabinet> list = baseMapper.selectList(queryWrapper);
        if (list.size() == 0) {
            return;
        }
        if (list.size() > 1) {
            throw new BusinessException("配电柜名称有重复");
        }
        if (StringUtils.isEmpty(distributionCabinet.getId())) {
            throw new BusinessException("配电柜名称已存在");
        }
        if (!distributionCabinet.getId().equals(list.get(0).getId())) {
            throw new BusinessException("配电柜名称已存在");
        }

    }


    /**
     * 校验参数必填
     */
    private void validParamRequired(DistributionCabinet distributionCabinet) {
        Assert.notNull(distributionCabinet, "参数为空");
        Assert.notNull(distributionCabinet.getSortNo(), "参数sortNo 为空");
        Assert.isTrue(StringUtils.isNotBlank(distributionCabinet.getName()), "名称为空");
        Assert.isTrue(StringUtils.isNotBlank(distributionCabinet.getDistributionCabinetTypeId()), "getDistributionCabinetTypeId 为空");
        Assert.isTrue(StringUtils.isNotBlank(distributionCabinet.getDistributionRoomId()), "getDistributionRoomId 为空");
    }

    /**
     * 校验参数格式
     */
    private void validParamFormat(DistributionCabinet distributionCabinet) {
        Assert.isTrue(distributionCabinet.getName() == null || distributionCabinet.getName().length() <= 32, "名称超长");
        Assert.isTrue(distributionCabinet.getDistributionRoomId() == null || distributionCabinet.getDistributionRoomId().length() <= 32, "distributionRoomId超长");
        Assert.isTrue(distributionCabinet.getTenantId() == null || distributionCabinet.getTenantId().length() <= 32, "租户id超长");
        Assert.isTrue(distributionCabinet.getDistributionCabinetTypeId() == null || distributionCabinet.getDistributionCabinetTypeId().length() <= 32, "getDistributionCabinetTypeId超长");
    }

    @Override
    public List<DistributionCabinet> getDistributionCabinets(DistributionCabinet distributionCabinet) {
        distributionCabinet.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        return baseMapper.getDistributionCabinets(distributionCabinet);
    }

    @Override
    public IPage<DistributionCabinet> getDistributionCabinets(Page page, DistributionCabinet distributionCabinet) {
        distributionCabinet.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        return baseMapper.getDistributionCabinets(page, distributionCabinet);
    }

    @Override
    public DistributionCabinet getDistributionCabinet(String id) {
        return baseMapper.getDistributionCabinet(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateDistributionCabinet(DistributionCabinet distributionCabinet) {
        Assert.notNull(distributionCabinet, "参数为空");
        DistributionCabinet originDistributionCabinet = getById(distributionCabinet.getId());
        Assert.notNull(originDistributionCabinet, "原配电柜不存在");
        validRepeat(distributionCabinet);
        validParamFormat(distributionCabinet);
        commonService.setModifyInfo(distributionCabinet);
        updateById(distributionCabinet);

        QueryWrapper qw = new QueryWrapper();
        qw.eq("distribution_cabinet_id", distributionCabinet.getId());
        distributionCabinetRefDeviceService.remove(qw);

        new LambdaUpdateChainWrapper<>(distributionCabinetAlarmConfigMapper)
                .eq(DistributionCabinetAlarmConfig::getCabinetId, distributionCabinet.getId())
                .remove();

        List<DistributionCabinetRefDevice> distributionCabinetRefDeviceList = distributionCabinet.getDistributionCabinetRefDeviceList();

        Assert.notEmpty(distributionCabinetRefDeviceList, "distributionCabinetRefDeviceList 不能为空");
        distributionCabinetRefDeviceList.forEach(distributionCabinetRefDevice -> {
            distributionCabinetRefDevice.setDistributionCabinetId(distributionCabinet.getId());
            distributionCabinetRefDeviceService.add(distributionCabinetRefDevice);
        });

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteBatch(List<DistributionCabinet> distributionCabinetList) {
        Assert.notEmpty(distributionCabinetList, "参数为空");
        List<String> ids = distributionCabinetList.stream().map(DistributionCabinet::getId).collect(Collectors.toList());

        QueryWrapper qw = new QueryWrapper();
        qw.in("distribution_cabinet_id", ids);
        distributionCabinetRefDeviceService.remove(qw);
        new LambdaUpdateChainWrapper<>(distributionCabinetAlarmConfigMapper)
                .in(DistributionCabinetAlarmConfig::getCabinetId, ids)
                .remove();
        removeByIds(ids);
    }

    @Override
    public List<DistributionCabinet> getRealTimeDistributionCabinetWithStatus(DistributionCabinet distributionCabinet) {
        distributionCabinet.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        List<DistributionCabinet> distributionCabinetList = baseMapper.getRealTimeDistributionCabinetWithStatus(distributionCabinet);

//        不需要排序 前端固定显示 modify by 2020-8-28 bug-配电房方案-电力监控页面加载时间长
//        属性根据sortNo 排序
//        distributionCabinetList.forEach(distributionCabinet1 -> {
//            distributionCabinet1.getDistributionCabinetRefDeviceList().forEach(distributionCabinetRefDevice -> {
//                distributionCabinetRefDevice.getDeviceAttributeStatusList().sort((a, b) -> {
//                    if (a.getSortNo() != null && b.getSortNo() != null && !a.getSortNo().equals(b.getSortNo())) {
//                        return a.getSortNo() > b.getSortNo() ? 1 : -1;
//                    }
//                    return 0;
//                });
//            });
//        });
        return distributionCabinetList;
    }

    @Override
    public DistributionCabinet getDistributionCabinetDetail(String id) {
        DistributionCabinet distributionCabinet = baseMapper.getDistributionCabinetDetail(id);
        if (distributionCabinet == null) {
            return null;
        }
        List<DistributionCabinetRefDevice> distributionCabinetRefDeviceList = distributionCabinet.getDistributionCabinetRefDeviceList();
//        2.0.0 迭代 排序 第一根据位置信息排序关联设备， 第二设备属性根据sortNo排序
        for (DistributionCabinetRefDevice distributionCabinetRefDevice : distributionCabinetRefDeviceList) {
            distributionCabinetRefDevice.getDeviceAttributeStatusList().sort((a, b) -> {
                if (a.getSortNo() != null && b.getSortNo() != null && !a.getSortNo().equals(b.getSortNo())) {
                    return a.getSortNo() > b.getSortNo() ? 1 : -1;
                }
                return 0;
            });
        }
        distributionCabinetRefDeviceList.sort((a, b) -> {
            if (a.getSortNo() != null && b.getSortNo() != null && !a.getSortNo().equals(b.getSortNo())) {
                return a.getSortNo() > b.getSortNo() ? 1 : -1;
            }
            return 0;
        });

        distributionCabinet.setDistributionCabinetRefDeviceList(distributionCabinetRefDeviceList);

        return distributionCabinet;
    }
}
